package com.ttg.utils;

//~--- non-JDK imports --------------------------------------------------------

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ttg.utils.sm.Base64Util;
import com.ttg.utils.sm.CryptoUtil;
import com.ttg.utils.sm.SM4Utils;
import com.ttg.utils.sm2.SM2SignVO;
import com.ttg.utils.sm2.SM2VerifySign;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

//~--- JDK imports ------------------------------------------------------------

//~--- classes ----------------------------------------------------------------

/**
 * Class TLinx2Util
 * Description
 * Create 2017-03-07 14:01:23
 *
 * @author Benny.YEE
 */
public class TLinx2Util {


    /**
     * 签名
     *
     * @param postMap
     * @return
     */
    public static String sign(Map<String, String> postMap) {
        String sign = null;

        try {

            /**
             * 1 A~z排序(加上open_key)
             */
            String sortStr = sort(postMap);
            System.out.println("====排序后的待签名字符串= " + sortStr);
            /**
             * 2 sha1加密(小写)
             */
            String sha1 = TLinxSHA1.SHA1(sortStr).toLowerCase();
            System.out.println("====sha1加密后的待签名字符串= " + sha1);
            /**
             * 3 md5加密(小写)
             */
            sign = TLinxMD5.MD5Encode(sha1).toLowerCase();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return sign;
    }

    /**
     * 验签
     *
     * @param respObject
     * @return
     */
    public static Boolean verifySign(JSONObject respObject,String pubKey) throws Exception{
        String respSign = respObject.get("sign").toString();
        respObject.remove("sign");    // 删除sign节点
        // 使用 TreeMap 对键进行排序，TreeMap 会自动按字母顺序排序键
        Map<String, Object> sortedMap = new TreeMap<>(respObject);
        // 将排序后的 Map 转换回 JSONObject
        JSONObject sortedJsonObject = new JSONObject(sortedMap);
        String origData =sortedJsonObject.toString();
        SM2SignVO result = SM2VerifySign.VerifySignSM2(CryptoUtil.hex2bin(pubKey), origData.getBytes(), Base64Util.decodeData(respSign), null, true);
        if (result != null && result.isVerify) {
            return true;
        }
        return false;
    }

    /**
     * AES加密，再二进制转十六进制(bin2hex)
     *
     * @param postmap 说明：
     * @throws Exception
     */
    public static void handleEncrypt(TreeMap<String, ?> datamap, TreeMap<String, String> postmap,String sm4Key) throws Exception {

        JSONObject dataobj = JSONObject.parseObject(JSON.toJSONString(datamap));
        SM4Utils sm4Utils = new SM4Utils();
        //String plainText, String secretKey,boolean isNoPadding,boolean isBase64,boolean isKeyHex
        String data =  SM4Utils.encryptDataECB(dataobj.toString(),sm4Key,false,true,false);
        System.out.println("====加密后的data= " + data);
        postmap.put("data", data);
    }


    public static Map<String, Object> handleDecrypt(String respStr, String sm4Key) throws Exception {
        SM4Utils sm4Utils = new SM4Utils();
        String decryptData = sm4Utils.decryptDataECB(respStr, sm4Key, false, false, false, false);
        System.out.println("解密数据=======>" + decryptData);
        JSONObject jsonObject = JSONObject.parseObject(decryptData);
        Map<String, Object> sortedMap = new TreeMap<>(jsonObject);
        return sortedMap;
    }

    /**
     * 签名
     *
     * @param postmap
     */
    public static void handleSign(TreeMap<String, String> postmap ,String priKey) throws Exception{



        JSONObject jsonObject = new JSONObject();
        jsonObject.put("data",postmap.get("data"));
        jsonObject.put("channel_id", postmap.get("channel_id"));
        jsonObject.put("secret", postmap.get("secret"));
        jsonObject.put("timestamp", postmap.get("timestamp"));

        // 使用 TreeMap 对键进行排序，TreeMap 会自动按字母顺序排序键
        Map<String, Object> sortedMap = new TreeMap<>(jsonObject);

        // 将排序后的 Map 转换回 JSONObject
        JSONObject sortedJsonObject = new JSONObject(sortedMap);

        String origData =sortedJsonObject.toString();

//        origData="{\"channel_id\":\"GCKD_001\",\"data\":\"e145a3be211aa3457c187f01618a3993a2955cfb5ccab045914c91ed60087802783392a3f83f7ac4190616fe10386062f7c693c8bfdeb93da1ef10d7c286d0b8ab9bf77432789fedda5017934eef6205\",\"secret\":\"041766c67f5ca99e8d869a60cdb5bd805ec17675cce74f366de8d597071bebbc3cbbea216a50bdd0ff9acf7502bf3d09e81ba47b603915c7cf5dd5544bf76b80e18211ac98c0ef19f55bab45367ed309b178cee30152dae25954e9509d1e3747265c2a8ac52058e6253adf8fa24781dbe6\",\"timestamp\":\"1735229531\"}";

        String returnData;
        SM2SignVO resultVO = SM2VerifySign.Sign2SM2(CryptoUtil.hex2bin(priKey), origData.getBytes("UTF-8"), null, true, true);
        if (resultVO != null && resultVO.getSm2_sign() != null && resultVO.getSm2_sign().length() > 0) {
            returnData = resultVO.getSm2_sign();
        } else {
            throw new Exception("SM2签名失败");
        }

        System.out.println("====已签名字符串= " + returnData);
        postmap.put("sign", returnData);
    }



    /**
     * 根据返回格式来选择post请求处理方式
     *
     * @param postmap
     * @param interfaceName
     * @param tarType
     * @return
     */
    public static String handlePostbyTarType(TreeMap<String, String> postmap, String interfaceName, String tarType) {
        if ("gzip".equals(tarType)) {
            return handlePostGZIP(postmap, interfaceName);
        } else {
            return handlePost(postmap, interfaceName);
        }
    }

    /**
     * 请求接口
     *
     * @param postmap
     * @return 响应字符串
     */
    public static String handlePost(TreeMap<String, String> postmap, String interfaceName) {
        String url = TestParams.OPEN_URL + interfaceName;
        System.out.println("====请求地址= " + url);
        if (url.contains("https")) {
            return HttpsUtil.httpMethodPostForJson(url, postmap, "UTF-8");
        } else {
            return HttpUtil.httpMethodPost(url, postmap, "UTF-8");
        }
    }

    public static String handlePostGZIP(TreeMap<String, String> postmap, String interfaceName) {
        String url = TestParams.OPEN_URL + interfaceName;
        if (url.contains("https")) {
            return HttpsUtil.httpMethodPostGZIP(url, postmap, "UTF-8");
        } else {
            return HttpUtil.httpMethodPostGZIP(url, postmap, "UTF-8");
        }
    }

    /**
     * 十六进制字符串转byte数组
     */
    public static byte[] hex2byte(String strhex) {
        if (strhex == null)
            return null;

        int l = strhex.length();
        if (l % 2 == 1)
            return null;

        byte[] b = new byte[l / 2];
        for (int i = 0; i != l / 2; ++i)
            b[i] = (byte) Integer.parseInt(strhex.substring(i * 2, i * 2 + 2), 16);

        return b;
    }

    /**
     * byte数组转十六进制字符串
     */
    public static String byte2hex(byte[] result) {
        StringBuffer sb = new StringBuffer(result.length * 2);
        for (int i = 0; i < result.length; i++) {
            int hight = ((result[i] >> 4) & 0x0f);
            int low = result[i] & 0x0f;
            sb.append(hight > 9 ? (char) ((hight - 10) + 'a') : (char) (hight + '0'));
            sb.append(low > 9 ? (char) ((low - 10) + 'a') : (char) (low + '0'));
        }
        return sb.toString();
    }

    /**
     * 排序
     *
     * @param paramMap
     * @return
     * @throws Exception
     */
    public static String sort(Map paramMap) throws Exception {
        String sort = "";
        TLinxMapUtil signMap = new TLinxMapUtil();
        if (paramMap != null) {
            String key;
            for (Iterator it = paramMap.keySet().iterator(); it.hasNext(); ) {
                key = (String) it.next();
                String value = ((paramMap.get(key) != null) && (!("".equals(paramMap.get(key).toString())))) ? paramMap.get(key).toString() : "";
                signMap.put(key, value);
            }
            signMap.sort();
            for (Iterator it = signMap.keySet().iterator(); it.hasNext(); ) {
                key = (String) it.next();
                sort = sort + key + "=" + signMap.get(key).toString() + "&";
            }
            if ((sort != null) && (!("".equals(sort)))) {
                sort = sort.substring(0, sort.length() - 1);
            }
        }
        return sort;
    }

    /**
     * unicode转中文
     *
     * @param unicode
     * @return
     */
    public static String unicodeToCn(String unicode) {
        /** 以 \ u 分割，因为java注释也能识别unicode，因此中间加了一个空格*/
        Pattern pattern = Pattern.compile("(\\\\u(\\p{XDigit}{4}))");
        Matcher matcher = pattern.matcher(unicode);
        char ch;
        while (matcher.find()) {
            ch = (char) Integer.parseInt(matcher.group(2), 16);
            unicode = unicode.replace(matcher.group(1), ch + "");
        }
        return unicode;
    }

    /**
     * Method main
     * Description 说明：
     *
     * @param args 说明：
     */
    public static void main(String[] args) {

    }
}


//~ Formatted by Jindent --- http://www.jindent.com
